#ifndef INTEGRATION_H
#define INTEGRATION_H

#include "Particle.h"

/// @enum IntegrationType Integration Method
enum IntegrationType
{
    SEMI_IMPLICIT_EULER,      ///< semi implicit euler
    LEAPFROG                  ///< modified leapfrog
};

/// @file Integration.h
/// @brief manages the integration of acceleration using 2 basic methods
/// @author Perseedoss Rajiv
/// @version 1.0
/// @date 23.07.11
/// Revision History :
/// Initial Version 23.07.11
/// @class Integration
/// @brief handles integration to find next position and velocity of particles

class Integration
{
public:
    /// @brief ctor
    /// @param[in] _integrationType the integration method
    /// @param[in] _timestep the timestep of the simulation
    Integration
            (
                const IntegrationType _integrationType,
                const ngl::Real _timestep
            );

    /// @brief integrate next velocity and position of a particle
    /// @param[in,out] io_currentParticle the particle that is being affected
    void integrateNext(Particle& io_currentParticle);

    /// @brief get the integration method
    inline IntegrationType getIntegrationType() const { return m_integrationType; }

    /// @brief sets the integration method
    /// @param[in] _v the new integration method
    inline void setIntegrationType(const IntegrationType _v) { m_integrationType = _v; }

    /// @brief set the integration method of the simulation
    /// @param[in] _v new integration method
    inline void setIntegrationType(const int _v) { m_integrationType = (IntegrationType)_v; }

    /// @brief get the timestep of the simulation
    inline ngl::Real getTimestep() const { return m_timestep; }

    /// @brief set the timestep of the simulation
    /// @param[in] _v new timestep
    inline void setTimestep(const ngl::Real _v) { m_timestep = _v; }


private:
    /// @brief integration method
    IntegrationType m_integrationType;

    /// @brief timestep of simulation
    ngl::Real m_timestep;

private:
    /// @brief integrate a particle using semi implicit euler
    /// @param[in,out] io_currentParticle the particle that is being affected
    void evaluateSemiImplicitEuler(Particle& io_currentParticle);

    /// @brief integrate a particle using leapfrog
    /// @param[in,out] io_currentParticle the particle that is being affected
    void evaluateLeapfrog(Particle& io_currentParticle);

};

#endif // INTEGRATION_H
